home *** CD-ROM | disk | FTP | other *** search
/ Aminet 38 / Aminet 38 (2000)(Schatztruhe)[!][Aug 2000].iso / Aminet / util / libs / asyncioppc.lha / asyncioppc / source / async_ppc.c next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  12.7 KB  |  530 lines

  1. #include <clib/dos_protos.h>
  2. #include <clib/exec_protos.h>
  3. #include <clib/powerpc_protos.h>
  4. #include <libraries/asyncio.h>
  5. #include <exec/memory.h>
  6. #include <string.h>
  7.  
  8. #define D_S(type,name) char a_##name[ sizeof( type )+3]; type *name=(type *)((LONG)(a_##name+3)&~3);
  9.  
  10. #ifndef MIN
  11. #define MIN(a,b) ((a)<(b)?(a):(b))
  12. #endif
  13.  
  14. //extern "C" void PPC_InitModules(),PPC_CleanupModules();
  15.  
  16. //void dummy()
  17. //{
  18. //PPC_InitModules();
  19. //PPC_CleanupModules();
  20. //}
  21.  
  22. static void copymem(UBYTE *s,UBYTE *d,ULONG len)
  23. {
  24. ULONG l=len&7;
  25. len-=l;
  26. while(l--) *(d++)=*(s++);
  27. while(len)
  28.     {
  29.     *(((double *)d)++)=*(((double *)s)++);
  30.     len-=8;
  31.     }
  32. }
  33.  
  34. static VOID AS_SendPacket(struct AsyncFile *file,APTR arg2)
  35. {
  36. file->af_Packet.sp_Pkt.dp_Port=&file->af_PacketPort;
  37. file->af_Packet.sp_Pkt.dp_Arg2=(LONG)arg2;
  38. PutXMsgPPC(file->af_Handler,&file->af_Packet.sp_Msg);
  39. file->af_PacketPending=TRUE;
  40. }
  41.  
  42. static LONG AS_WaitPacket(AsyncFile *file)
  43. {
  44. LONG bytes;
  45. if(file->af_PacketPending)
  46.     {
  47.     while(1)
  48.         {
  49.         file->af_PacketPort.mp_Flags=PA_SIGNAL;
  50.         RemovePPC((struct Node *)WaitPort(&file->af_PacketPort));
  51. /*
  52. This dummy call is absolutely necessary to avoid lock-up
  53. in some strange cases, e.g. accessing very long files !!, Dont remove it !!
  54. */
  55.         SPrintF(0,0);
  56.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  57.         file->af_PacketPending=FALSE;
  58.         bytes=file->af_Packet.sp_Pkt.dp_Res1;
  59.         if(bytes>=0) return bytes;
  60.         if(ErrorReport(file->af_Packet.sp_Pkt.dp_Res2,REPORT_STREAM,file->af_File,NULL)) return -1;
  61.         AS_SendPacket(file,file->af_Buffers[file->af_ReadMode?file->af_CurrentBuf:1-file->af_CurrentBuf]);
  62.         }
  63.     }
  64. SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
  65. return file->af_Packet.sp_Pkt.dp_Res1;
  66. }
  67.  
  68. static VOID AS_RecordSyncFailure(struct AsyncFile *file)
  69. {
  70. file->af_LastRes1=file->af_Packet.sp_Pkt.dp_Res1;
  71. file->af_LastBytesLeft=file->af_BytesLeft;
  72. file->af_Packet.sp_Pkt.dp_Res1=-1;
  73. file->af_Packet.sp_Pkt.dp_Res2=IoErr();
  74. file->af_BytesLeft=0;
  75. }
  76.  
  77. static VOID AS_RequeuePacket(AsyncFile *file)
  78. {
  79. AddHeadPPC(&file->af_PacketPort.mp_MsgList,&file->af_Packet.sp_Msg.mn_Node);
  80. file->af_PacketPending=TRUE;
  81. }
  82.  
  83. struct AsyncFile *AS_OpenAsyncFH(BPTR handle,LONG mode,LONG bufferSize,BOOL closeIt)
  84. {
  85. FileHandle *fh;
  86. AsyncFile *file=NULL;
  87. BPTR lock=NULL;
  88. LONG blockSize,blockSize2;
  89. D_S(struct InfoData,infoData);
  90. if(mode==MODE_READ)
  91.     {
  92.     if(handle) lock=DupLockFromFH(handle);
  93.     }
  94. else
  95.     {
  96.     if(mode==MODE_APPEND)
  97.         {
  98.         if(handle)
  99.             {
  100.             if(Seek(handle,0,OFFSET_END)<0)
  101.                 {
  102.                 if(closeIt) Close(handle);
  103.                 handle=NULL;
  104.                 }
  105.             }
  106.         }
  107.     if(handle) lock=ParentOfFH(handle);
  108.     }
  109. if(handle)
  110.     {
  111.     blockSize=512;
  112.     blockSize2=1024;
  113.     if(lock)
  114.         {
  115.         if(Info(lock,infoData))
  116.             {
  117.             blockSize=infoData->id_BytesPerBlock;
  118.             blockSize2=blockSize*2;
  119.             bufferSize=((bufferSize+blockSize2-1)/blockSize2)*blockSize2;
  120.             }
  121.         UnLock(lock);
  122.         }
  123.     for(;;)
  124.         {
  125.         if(file=AllocVecPPC(sizeof(AsyncFile)+bufferSize+15,MEMF_PUBLIC|MEMF_ANY,0)) break;
  126.         else
  127.             {
  128.             if(bufferSize>blockSize2) bufferSize-=blockSize2;
  129.             else break;
  130.             }
  131.         }
  132.     if(file)
  133.         {
  134.         file->af_File=handle;
  135.         file->af_ReadMode=(mode==MODE_READ);
  136.         file->af_BlockSize=blockSize;
  137.         file->af_CloseFH=closeIt;
  138.         fh=(FileHandle *)BADDR(file->af_File);
  139.         file->af_Handler=fh->fh_Type;
  140.         file->af_BufferSize=(ULONG)bufferSize/2;
  141.         file->af_Buffers[0]=(UBYTE *)(((ULONG)file+sizeof(AsyncFile)+15)&0xfffffff0);
  142.         file->af_Buffers[1]=file->af_Buffers[0]+file->af_BufferSize;
  143.         file->af_CurrentBuf=0;
  144.         file->af_SeekOffset=0;
  145.         file->af_PacketPending=FALSE;
  146.         file->af_SeekPastEOF=FALSE;
  147.         file->af_PacketPort.mp_MsgList.lh_Head=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
  148.         file->af_PacketPort.mp_MsgList.lh_Tail=NULL;
  149.         file->af_PacketPort.mp_MsgList.lh_TailPred=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
  150.         file->af_PacketPort.mp_Node.ln_Type=NT_MSGPORT;
  151.         file->af_PacketPort.mp_Node.ln_Name=NULL;
  152.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  153.         file->af_PacketPort.mp_SigBit=SIGB_SINGLE;
  154.         file->af_PacketPort.mp_SigTask=FindTask(NULL);
  155.         file->af_Packet.sp_Pkt.dp_Link=&file->af_Packet.sp_Msg;
  156.         file->af_Packet.sp_Pkt.dp_Arg1=fh->fh_Arg1;
  157.         file->af_Packet.sp_Pkt.dp_Arg3=file->af_BufferSize;
  158.         file->af_Packet.sp_Pkt.dp_Res1=0;
  159.         file->af_Packet.sp_Pkt.dp_Res2=0;
  160.         file->af_Packet.sp_Msg.mn_Node.ln_Name=(STRPTR)&file->af_Packet.sp_Pkt;
  161.         file->af_Packet.sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
  162.         file->af_Packet.sp_Msg.mn_Length=sizeof(struct StandardPacket);
  163.         if(mode==MODE_READ)
  164.             {
  165.             file->af_Packet.sp_Pkt.dp_Type=ACTION_READ;
  166.             file->af_BytesLeft=0;
  167.             file->af_Offset=file->af_Buffers[1];
  168.             if(file->af_Handler) AS_SendPacket(file,file->af_Buffers[0]);
  169.             }
  170.         else
  171.             {
  172.             file->af_Packet.sp_Pkt.dp_Type=ACTION_WRITE;
  173.             file->af_BytesLeft=file->af_BufferSize;
  174.             file->af_Offset=file->af_Buffers[0];
  175.             }
  176.         }
  177.     else
  178.         {
  179.         if(closeIt) Close(handle);
  180.         }
  181.     }
  182. return file;
  183. }
  184.  
  185. struct AsyncFile * __saveds OpenAsyncPPC(struct AsyncIOBase *base,STRPTR fileName,LONG mode,LONG bufferSize)
  186. {
  187. static const WORD PrivateOpenModes[]={MODE_OLDFILE,MODE_NEWFILE,MODE_READWRITE};
  188. BPTR handle;
  189. AsyncFile *file=NULL;
  190. if(handle=Open(fileName,PrivateOpenModes[mode]))
  191.     {
  192.     if(!(file=AS_OpenAsyncFH(handle,mode,bufferSize,TRUE))) Close(handle);
  193.     }
  194. return file;
  195. }
  196.  
  197. struct AsyncFile * __saveds OpenAsyncFromFHPPC(struct AsyncIOBase *base,BPTR handle,LONG mode,LONG bufferSize)
  198. {
  199. return AS_OpenAsyncFH(handle,mode,bufferSize,FALSE);
  200. }
  201.  
  202. LONG __saveds CloseAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file)
  203. {
  204. LONG result;
  205. if(file)
  206.     {
  207.     result=AS_WaitPacket(file);
  208.     if(result>=0)
  209.         {
  210.         if(!file->af_ReadMode)
  211.             {
  212.             if(file->af_BufferSize>file->af_BytesLeft)
  213.                 {
  214.                 result=Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft);
  215.                 }
  216.             }
  217.         }
  218.     if(file->af_CloseFH) Close(file->af_File);
  219.     FreeVecPPC(file);
  220.     }
  221. else result=-1;
  222. return result;
  223. }
  224.  
  225. LONG __saveds ReadAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  226. {
  227. LONG totalBytes=0;
  228. LONG bytesArrived;
  229. while(numBytes>file->af_BytesLeft)
  230.     {
  231.     copymem(file->af_Offset,buffer,file->af_BytesLeft);
  232.     numBytes-=file->af_BytesLeft;
  233.     buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  234.     totalBytes+=file->af_BytesLeft;
  235.     file->af_BytesLeft=0;
  236.     bytesArrived=AS_WaitPacket(file);
  237.     if(bytesArrived<=0)
  238.         {
  239.         if(bytesArrived==0) return(totalBytes);
  240.         return -1;
  241.         }
  242.     AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  243.     if(file->af_SeekOffset>bytesArrived) file->af_SeekOffset=bytesArrived;
  244.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+file->af_SeekOffset;
  245.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  246.     file->af_BytesLeft=bytesArrived-file->af_SeekOffset;
  247.     file->af_SeekOffset=0;
  248.     }
  249. copymem(file->af_Offset,buffer,numBytes);
  250. file->af_BytesLeft-=numBytes;
  251. file->af_Offset+=numBytes;
  252. return totalBytes+numBytes;
  253. }
  254.  
  255. LONG __saveds PeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  256. {
  257. if(!file->af_BytesLeft)
  258.     {
  259.     LONG bytes;
  260.     if((bytes=ReadAsyncPPC(base,file,&bytes,1))<=0) return bytes;
  261.     --file->af_Offset;
  262.     ++file->af_BytesLeft;
  263.     }
  264. numBytes=MIN(numBytes,file->af_BytesLeft);
  265. copymem(file->af_Offset,buffer,numBytes);
  266. return numBytes;
  267. }
  268.  
  269. LONG __saveds ReadCharAsyncPPC(struct AsyncIOBase *base,AsyncFile *file)
  270. {
  271. UBYTE    ch;
  272. if(file->af_BytesLeft)
  273.     {
  274.     ch=*file->af_Offset;
  275.     --file->af_BytesLeft;
  276.     ++file->af_Offset;
  277.     return ch;
  278.     }
  279. if(ReadAsyncPPC(base,file,&ch,1)>0) return ch;
  280. return -1;
  281. }
  282.  
  283. STRPTR __saveds FGetsLenAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes,LONG *len)
  284. {
  285. UBYTE *p;
  286. LONG    length=0;
  287. p=(UBYTE *)buf;
  288. if(--numBytes<=0) return 0;
  289. while(TRUE)
  290.     {
  291.     UBYTE *ptr;
  292.     LONG i,count;
  293.     ptr=(UBYTE *)file->af_Offset;
  294.     if(count=file->af_BytesLeft)
  295.         {
  296.         count=MIN(count,numBytes);
  297.         for(i=0;(i<count)&&(*ptr!='\n');++i) *p++=*ptr++;
  298.         length+=i;
  299.         if(i<count)
  300.             {
  301.             *p++='\n';
  302.             ++i;
  303.             length+=1;
  304.             }
  305.         file->af_BytesLeft-=i;
  306.         file->af_Offset+=i;
  307.         if((i>=numBytes)||(*(p-1)=='\n')) break;
  308.         numBytes-=i;
  309.         }
  310.     if(ReadAsyncPPC(base,file,p,1)<1) break;
  311.     --numBytes;
  312.     ++length;
  313.     if(*p++=='\n') break;
  314.     }
  315. *p='\0';
  316. *len=length;
  317. if(p==(UBYTE *)buf) return 0;
  318. return buf;
  319. }
  320.  
  321. STRPTR __saveds FGetsAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes)
  322. {
  323. LONG len;
  324. return FGetsLenAsyncPPC(base,file,buf,numBytes,&len);
  325. }
  326.  
  327. LONG __saveds ReadLineAsyncPPC(struct AsyncIOBase *base,AsyncFile *file,APTR buffer,LONG bufSize)
  328. {
  329. LONG    len;
  330. if(FGetsLenAsyncPPC(base,file,buffer,bufSize,&len))
  331.     {
  332.     UBYTE *end;
  333.     end=((UBYTE *)buffer)+len-1;
  334.     if(*end!='\n')
  335.         {
  336.         UBYTE    ch=0;
  337.         while(TRUE)
  338.             {
  339.             UBYTE *ptr;
  340.             LONG i,count;
  341.             ptr=(UBYTE *)file->af_Offset;
  342.             if(count=file->af_BytesLeft)
  343.                 {
  344.                 for(i=0;(i<count)&& (*ptr!='\n');++i,++ptr)
  345.                     {
  346.                     }
  347.                 if(i<count)
  348.                     {
  349.                     ch='\n';
  350.                     ++i;
  351.                     }
  352.                 file->af_BytesLeft-=i;
  353.                 file->af_Offset+=i;
  354.                 if(i<count) break;
  355.                 }
  356.             if(ReadAsyncPPC(base,file,&ch,1)<1) break;
  357.             if(ch=='\n') break;
  358.             }
  359.         if(ch=='\n')
  360.             {
  361.             *end++='\n';
  362.             *end='\0';
  363.             }
  364.         }
  365.     }
  366. return len;
  367. }
  368.  
  369. static __saveds ULONG GetFileSize(AsyncFile *file,LONG *size)
  370. {
  371. D_S(struct FileInfoBlock,fib);
  372. if(!ExamineFH(file->af_File,fib))
  373.     {
  374.     AS_RecordSyncFailure(file);
  375.     return FALSE;
  376.     }
  377. *size=fib->fib_Size;
  378. return TRUE;
  379. }
  380.  
  381. LONG __saveds SeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,LONG position,LONG mode)
  382. {
  383. LONG current,target,roundTarget,filePos;
  384. LONG minBuf,maxBuf,bytesArrived,diff;
  385. LONG fileSize;
  386. bytesArrived=AS_WaitPacket(file);
  387. if(bytesArrived<0)
  388.     {
  389.     if(file->af_SeekPastEOF)
  390.         {
  391.         bytesArrived=file->af_LastRes1;
  392.         file->af_BytesLeft=file->af_LastBytesLeft;
  393.         }
  394.     else return -1;
  395.     }
  396. if(file->af_ReadMode)
  397.     {
  398.     filePos=Seek(file->af_File,0,OFFSET_CURRENT);
  399.     if(filePos<0)
  400.         {
  401.         AS_RecordSyncFailure(file);
  402.         return -1;
  403.         }
  404.     current=filePos-(file->af_BytesLeft+bytesArrived)+file->af_SeekOffset;
  405.     if(mode==MODE_CURRENT) target=current+position;
  406.     else if(mode==MODE_START) target=position;
  407.     else 
  408.         {
  409.         if(!GetFileSize(file,&fileSize)) return -1;
  410.         target=fileSize+position;
  411.         }
  412.     minBuf=current-(LONG)(file->af_Offset-file->af_Buffers[1-file->af_CurrentBuf]);
  413.     maxBuf=current+file->af_BytesLeft+bytesArrived;
  414.     diff=target-current;
  415.     if((target<minBuf)||(target>=maxBuf))
  416.         {
  417.         if(target>=maxBuf)
  418.             {
  419.             if(!GetFileSize(file,&fileSize)) return -1;
  420.             if(target>fileSize)
  421.                 {
  422.                 file->af_SeekPastEOF=TRUE;
  423.                 SetIoErr(ERROR_SEEK_ERROR);
  424.                 AS_RecordSyncFailure(file);
  425.                 return -1;
  426.                 }
  427.             }
  428.         roundTarget=(target/file->af_BlockSize)*file->af_BlockSize;
  429.         if(Seek(file->af_File,roundTarget-filePos,OFFSET_CURRENT)<0)
  430.             {
  431.             AS_RecordSyncFailure(file);
  432.             return -1;
  433.             }
  434.         AS_SendPacket(file,file->af_Buffers[0]);
  435.         file->af_SeekOffset=target-roundTarget;
  436.         file->af_BytesLeft=0;
  437.         file->af_CurrentBuf=0;
  438.         file->af_Offset=file->af_Buffers[1];
  439.         }
  440.     else if((target<current)||(diff<=file->af_BytesLeft))
  441.         {
  442.         AS_RequeuePacket(file);
  443.         file->af_BytesLeft-=diff;
  444.         file->af_Offset+=diff;
  445.         if(file->af_SeekPastEOF) file->af_Packet.sp_Pkt.dp_Res1=file->af_LastRes1;
  446.         }
  447.     else
  448.         {
  449.         AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  450.         diff-=file->af_BytesLeft-file->af_SeekOffset;
  451.         file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+diff;
  452.         file->af_BytesLeft=bytesArrived-diff;
  453.         file->af_SeekOffset=0;
  454.         file->af_CurrentBuf=1-file->af_CurrentBuf;
  455.         }
  456.     }
  457. else
  458.     {
  459.     if(file->af_BufferSize>file->af_BytesLeft)
  460.         {
  461.         if(Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft)<0)
  462.             {
  463.             AS_RecordSyncFailure(file);
  464.             return -1;
  465.             }
  466.         }
  467.     current=Seek(file->af_File,position,mode);
  468.     if(current<0)
  469.         {
  470.         AS_RecordSyncFailure(file);
  471.         return -1;
  472.         }
  473.     file->af_BytesLeft=file->af_BufferSize;
  474.     file->af_CurrentBuf=0;
  475.     file->af_Offset=file->af_Buffers[0];
  476.     }
  477. if(file->af_SeekPastEOF) file->af_SeekPastEOF=FALSE;
  478. SetIoErr(0);
  479. return current;
  480. }
  481.  
  482. LONG __saveds WriteAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  483. {
  484. LONG totalBytes=0;
  485. if(!file->af_Handler)
  486.     {
  487.     file->af_Offset=file->af_Buffers[0];
  488.     file->af_BytesLeft=file->af_BufferSize;
  489.     return numBytes;
  490.     }
  491. while(numBytes>file->af_BytesLeft)
  492.     {
  493.     if(file->af_BytesLeft)
  494.         {
  495.         copymem(buffer,file->af_Offset,file->af_BytesLeft);
  496.         numBytes-=file->af_BytesLeft;
  497.         buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  498.         totalBytes+=file->af_BytesLeft;
  499.         }
  500.     if(AS_WaitPacket(file)<0) return -1;
  501.     AS_SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);
  502.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  503.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf];
  504.     file->af_BytesLeft=file->af_BufferSize;
  505.     }
  506. copymem(buffer,file->af_Offset,numBytes);
  507. file->af_BytesLeft-=numBytes;
  508. file->af_Offset+=numBytes;
  509. return totalBytes+numBytes;
  510. }
  511.  
  512. LONG __saveds WriteCharAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,ULONG ch)
  513. {
  514. UBYTE    c;
  515. if(file->af_BytesLeft)
  516.     {
  517.     *file->af_Offset=ch;
  518.     --file->af_BytesLeft;
  519.     ++file->af_Offset;
  520.     return 1;
  521.     }
  522. c=ch;
  523. return WriteAsyncPPC(base,file,&c,1);
  524. }
  525.  
  526. LONG __saveds WriteLineAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR line)
  527. {
  528. return WriteAsyncPPC(base,file,line,strlen(line));
  529. }
  530.